﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Taste
{
    /// <summary>
    /// A series of predefined transitions to simplify state definitions.
    /// </summary>
    public static class Transitions
    {
        /// <summary>
        /// Reject the transition.
        /// </summary>
        public static Action<IStateTransition> Reject()
        {
            return tr => tr.Reject();
        }

        /// <summary>
        /// Accept the transition and enter the state specified as userdata.
        /// </summary>
        public static Action<IStateTransition<TState>> FollowUserData<TState>()
             where TState : struct
        {
            return tr =>
            {
                if(tr.UserData is TState)
                    tr.AcceptAndEnter((TState)tr.UserData, null);
                else
                    tr.Reject();
            };
        }

        /// <summary>
        /// Accept the transition and enter the specified state.
        /// </summary>
        public static Action<IStateTransition<TState>> FollowTo<TState>(TState nextState, object userData = null)
            where TState : struct
        {
            return tr => tr.AcceptAndEnter(nextState, userData);
        }

        /// <summary>
        /// Accept the transition and enter one of the specified states depending of the boolean value of the transition's userdata.
        /// </summary>
        /// <param name="stateIfTrue">The state to enter if the transition's userdata is true.</param>
        /// <param name="stateIfFalse">The state to enter if the transition's userdata is false.</param>
        /// <param name="userData">The custom data to pass to the entered state</param>
        public static Action<IStateTransition<TState>> FollowIfTrue<TState>(TState stateIfTrue, TState stateIfFalse, object userData = null)
            where TState : struct
        {
            return tr => tr.AcceptAndEnter((bool)tr.UserData ? stateIfTrue : stateIfFalse, userData);
        }

        /// <summary>
        /// Accept the transition and enter one of the specified states depending of the value of the transition's userdata.
        /// </summary>
        /// <param name="stateIfNull">The state to enter if the transition's userdata is null.</param>
        /// <param name="stateIfNotNull">The state to enter if the transition's userdata is not null.</param>
        /// <param name="userData">The custom data to pass to the entered state</param>
        public static Action<IStateTransition<TState>> FollowIfNull<TState>(TState stateIfNull, TState stateIfNotNull, object userData = null)
            where TState : struct
        {
            return tr => tr.AcceptAndEnter(tr.UserData == null ? stateIfNull : stateIfNotNull, userData);
        }
    }
}
